using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 窝瓜攻击策略 - 跳向最近的僵尸并压扁造成范围伤害
/// </summary>
public class SquashAttackStrategy : AttackStrategyBase
{
    private Coroutine m_AttackCoroutine;
    private SquashSkillData m_SquashData;

    public SquashAttackStrategy(SkillData data)
    {
        AttackData = data;
        if (data is SquashSkillData squashData)
        {
            m_SquashData = squashData;
        }
    }

    public override void Execute(Entity target)
    {
        base.Execute(target);

        if (Owner == null)
        {
            Logger.LogWarning("SquashAttackStrategy", "Owner为空，无法执行攻击");
            return;
        }

        // 启动攻击协程
        if (m_AttackCoroutine == null)
        {
            m_AttackCoroutine = Owner.StartCoroutine(AttackRoutine());
        }
    }

    /// <summary>
    /// 攻击协程
    /// </summary>
    private IEnumerator AttackRoutine()
    {
        if (m_SquashData == null)
        {
            Logger.LogWarning("SquashAttackStrategy", "SquashSkillData为空");
            yield break;
        }

        // 查找目标范围内的最近僵尸
        Zombie targetZombie = FindNearestZombie();
        if (targetZombie == null)
        {
            Logger.LogWarning("SquashAttackStrategy", "未找到目标僵尸");
            yield break;
        }

        // 等待僵尸进入攻击范围
        yield return Owner.StartCoroutine(WaitForZombieInRange(targetZombie));
        
        // 再次检查目标是否仍然有效
        if (targetZombie == null || targetZombie.HealthComponent.IsDead)
        {
            Logger.LogWarning("SquashAttackStrategy", "目标僵尸已无效");
            yield break;
        }

        // 保存目标位置（用于后续跳跃）
        Vector3 targetPosition = targetZombie.transform.position;
        float distanceToTarget = Vector3.Distance(Owner.transform.position, targetPosition);
        bool shouldJump = distanceToTarget > m_SquashData.AttackRange && distanceToTarget <= m_SquashData.JumpRange;

        // 等待攻击延迟
        yield return new WaitForSeconds(m_SquashData.AttackDelay);

        // 触发攻击动画（蓄力动作，通过FSM）
        if (Owner.FSMComponent != null)
        {
            Owner.FSMComponent.ChangeStatus(FSMType.Attack);
        }

        // 等待攻击动画（蓄力动作）播放完成
        yield return Owner.StartCoroutine(WaitForAttackAnimation());

        // 攻击动画（蓄力）播放完成后，切换到Idle状态（跳跃时播放idle动画）
        if (Owner.FSMComponent != null)
        {
            Owner.FSMComponent.ChangeStatus(FSMType.Idle);
        }

        // 等待一小段时间，确保状态切换完成
        yield return new WaitForSeconds(0.1f);

        // 如果僵尸在跳跃范围内，跳跃到僵尸位置（此时播放idle动画）
        if (shouldJump && targetZombie != null && !targetZombie.HealthComponent.IsDead)
        {
            // 更新目标位置（僵尸可能已经移动）
            targetPosition = targetZombie.transform.position;
            // 跳跃到目标位置（跳跃过程中播放idle动画）
            yield return Owner.StartCoroutine(JumpToTarget(targetPosition));
        }

        // 获取植物所在的Cell
        Cell cell = GetPlantCell();
        if (cell == null)
        {
            Logger.LogWarning("SquashAttackStrategy", "无法获取植物所在的Cell");
            yield break;
        }

        // 查找同一行的所有僵尸
        List<Zombie> zombiesInRow = FindZombiesInRow(cell.Row);
        
        // 对当前行攻击范围内的所有僵尸造成伤害
        Vector3 attackCenter = Owner.transform.position;
        foreach (var zombie in zombiesInRow)
        {
            if (zombie != null && !zombie.HealthComponent.IsDead)
            {
                // 检查僵尸是否在攻击范围内
                float distance = Vector3.Distance(attackCenter, zombie.transform.position);
                if (distance <= m_SquashData.AttackRange)
                {
                    long damage = m_SquashData.AttackDamage;
                    zombie.HealthComponent.TakeDamage(damage);
                    Logger.Log("SquashAttackStrategy", $"{Owner.name} 对 {zombie.name} 造成 {damage} 点伤害（距离: {distance:F2}）");
                    
                    // 如果技能数据有Effects列表，执行效果
                    if (AttackData != null && AttackData.Effects != null && AttackData.Effects.Count > 0)
                    {
                        SkillExecutor.Execute(AttackData.Effects, Owner, zombie);
                    }
                }
            }
        }

        // 如果是一次性使用，等待一小段时间后杀死植物
        // 等待时间让伤害和攻击动画有时间显示
        if (m_SquashData.IsOneTimeUse && Owner != null)
        {
            // 等待一小段时间，确保伤害已应用，攻击动画开始播放
            yield return new WaitForSeconds(0.2f);
            
            // 杀死植物
            if (Owner != null && Owner.HealthComponent != null && !Owner.HealthComponent.IsDead)
            {
                // 直接造成足够杀死植物的伤害
                long currentHealth = Owner.HealthComponent.CurHealth;
                Owner.HealthComponent.TakeDamage(currentHealth);
                Logger.Log("SquashAttackStrategy", $"{Owner.name} 触发攻击后死亡");
                
                // 触发死亡状态（HealthComponent会自动触发，但为了确保，我们也可以手动触发）
                if (Owner.FSMComponent != null && Owner.HealthComponent.IsDead)
                {
                    Owner.FSMComponent.ChangeStatus(FSMType.Dead);
                }
            }
        }

        m_AttackCoroutine = null;
    }

    /// <summary>
    /// 查找最近的僵尸
    /// </summary>
    private Zombie FindNearestZombie()
    {
        var entityService = ServiceManager.Instance.GetService<EntityService>();
        if (entityService != null)
        {
            // 使用目标搜索范围查找最近的敌人
            Entity nearestEnemy = entityService.FindNearestEnemy(Owner, m_SquashData.TargetSearchRange);
            if (nearestEnemy is Zombie zombie)
            {
                Logger.Log("SquashAttackStrategy", $"找到目标僵尸: {zombie.name}");
                return zombie;
            }
        }
        
        // 降级方案：使用FindObjectsOfType
        Zombie[] allZombies = UnityEngine.Object.FindObjectsOfType<Zombie>();
        Zombie nearestZombie = null;
        float nearestDistance = float.MaxValue;
        Vector3 ownerPos = Owner.transform.position;

        foreach (var zombie in allZombies)
        {
            if (zombie == null || zombie.HealthComponent.IsDead) continue;
            
            float distance = Vector3.Distance(ownerPos, zombie.transform.position);
            if (distance <= m_SquashData.TargetSearchRange && distance < nearestDistance)
            {
                nearestDistance = distance;
                nearestZombie = zombie;
            }
        }

        if (nearestZombie != null)
        {
            Logger.Log("SquashAttackStrategy", $"找到目标僵尸: {nearestZombie.name} (距离: {nearestDistance:F2})");
        }
        else
        {
            Logger.LogWarning("SquashAttackStrategy", $"在搜索范围 {m_SquashData.TargetSearchRange} 内未找到僵尸");
        }

        return nearestZombie;
    }

    /// <summary>
    /// 获取植物所在的Cell
    /// </summary>
    private Cell GetPlantCell()
    {
        if (Owner == null) return null;

        // 植物是Cell的子对象，通过父对象获取Cell组件
        Transform parent = Owner.transform.parent;
        if (parent != null)
        {
            Cell cell = parent.GetComponent<Cell>();
            if (cell != null)
            {
                return cell;
            }
        }

        // 如果父对象没有Cell组件，尝试在场景中查找
        // 通过位置查找最近的Cell
        Cell[] allCells = UnityEngine.Object.FindObjectsOfType<Cell>();
        Cell nearestCell = null;
        float nearestDistance = float.MaxValue;

        foreach (var cell in allCells)
        {
            float distance = Vector3.Distance(Owner.transform.position, cell.transform.position);
            if (distance < nearestDistance)
            {
                nearestDistance = distance;
                nearestCell = cell;
            }
        }

        return nearestCell;
    }

    /// <summary>
    /// 查找指定行的所有僵尸
    /// </summary>
    private List<Zombie> FindZombiesInRow(int row)
    {
        List<Zombie> zombiesInRow = new List<Zombie>();

        // 使用EntityService查找所有实体
        var entityService = ServiceManager.Instance.GetService<EntityService>();
        if (entityService != null)
        {
            var allEntities = entityService.GetAllEntities();
            foreach (var entity in allEntities)
            {
                if (entity is Zombie zombie && !zombie.HealthComponent.IsDead)
                {
                    // 检查僵尸是否在同一行
                    if (IsZombieInRow(zombie, row))
                    {
                        zombiesInRow.Add(zombie);
                    }
                }
            }
        }
        else
        {
            // 降级方案：使用FindObjectsOfType
            Zombie[] allZombies = UnityEngine.Object.FindObjectsOfType<Zombie>();
            foreach (var zombie in allZombies)
            {
                if (!zombie.HealthComponent.IsDead && IsZombieInRow(zombie, row))
                {
                    zombiesInRow.Add(zombie);
                }
            }
        }

        Logger.Log("SquashAttackStrategy", $"在第 {row} 行找到 {zombiesInRow.Count} 个僵尸");
        return zombiesInRow;
    }

    /// <summary>
    /// 检查僵尸是否在指定行
    /// </summary>
    private bool IsZombieInRow(Zombie zombie, int targetRow)
    {
        if (zombie == null) return false;

        // 方法1：找到僵尸最近的Cell（所有行），如果这个Cell的行号等于目标行，则僵尸在该行
        // 这是最准确的方法，因为可以确保僵尸真的在目标行的某个Cell附近
        Cell[] allCells = UnityEngine.Object.FindObjectsOfType<Cell>();
        if (allCells == null || allCells.Length == 0) return false;

        Cell nearestCell = null;
        float nearestDistance = float.MaxValue;

        // 查找所有Cell中距离僵尸最近的（不限制行）
        foreach (var cell in allCells)
        {
            if (cell == null) continue;
            
            float distance = Vector3.Distance(zombie.transform.position, cell.transform.position);
            if (distance < nearestDistance)
            {
                nearestDistance = distance;
                nearestCell = cell;
            }
        }

        // 如果最近的Cell在目标行，且距离在合理范围内（比如1.5个单位，大约是Cell的一半宽度）
        // 这样可以确保僵尸真的在目标行的格子范围内
        if (nearestCell != null && nearestCell.Row == targetRow && nearestDistance < 1.5f)
        {
            Logger.Log("SquashAttackStrategy", $"僵尸 {zombie.name} 在第 {targetRow} 行（最近Cell: Row={nearestCell.Row}, Col={nearestCell.Column}, 距离={nearestDistance:F2}）");
            return true;
        }

        // 方法2：通过Y坐标判断（备用方法，但更严格）
        // 获取目标行的所有Cell，计算Y坐标范围
        float minY = float.MaxValue;
        float maxY = float.MinValue;
        int cellCount = 0;
        
        foreach (var cell in allCells)
        {
            if (cell != null && cell.Row == targetRow)
            {
                float cellY = cell.transform.position.y;
                if (cellY < minY) minY = cellY;
                if (cellY > maxY) maxY = cellY;
                cellCount++;
            }
        }

        if (cellCount > 0)
        {
            // 计算Y坐标容差（Cell高度的一半，假设Cell高度约为1单位）
            float yTolerance = 0.3f;
            float zombieY = zombie.transform.position.y;
            
            // 僵尸的Y坐标必须在目标行的Y坐标范围内（加上容差）
            if (zombieY >= minY - yTolerance && zombieY <= maxY + yTolerance)
            {
                // 进一步检查：僵尸必须距离目标行的某个Cell足够近
                // 这样可以避免其他行的僵尸因为Y坐标接近而被误判
                foreach (var cell in allCells)
                {
                    if (cell != null && cell.Row == targetRow)
                    {
                        float distance = Vector3.Distance(zombie.transform.position, cell.transform.position);
                        if (distance < 1.5f)
                        {
                            Logger.Log("SquashAttackStrategy", $"僵尸 {zombie.name} 在第 {targetRow} 行（Y坐标匹配，距离Cell Row={cell.Row}, Col={cell.Column} 为 {distance:F2}）");
                            return true;
                        }
                    }
                }
            }
        }

        Logger.Log("SquashAttackStrategy", $"僵尸 {zombie.name} 不在第 {targetRow} 行（最近Cell: Row={nearestCell?.Row ?? -1}, 距离={nearestDistance:F2}）");
        return false;
    }

    /// <summary>
    /// 等待僵尸进入攻击范围
    /// </summary>
    private IEnumerator WaitForZombieInRange(Zombie targetZombie)
    {
        if (targetZombie == null || Owner == null)
        {
            yield break;
        }

        float maxWaitTime = 10f; // 最大等待时间（防止无限等待）
        float elapsedTime = 0f;
        float checkInterval = 0.1f; // 检查间隔
        float nextCheckTime = 0f;

        Logger.Log("SquashAttackStrategy", $"{Owner.name} 等待僵尸 {targetZombie.name} 进入攻击范围 {m_SquashData.AttackRange}");

        while (elapsedTime < maxWaitTime && Owner != null && targetZombie != null && !targetZombie.HealthComponent.IsDead)
        {
            elapsedTime += Time.deltaTime;
            
            if (elapsedTime >= nextCheckTime)
            {
                float distance = Vector3.Distance(Owner.transform.position, targetZombie.transform.position);
                
                // 如果僵尸在攻击范围内，可以开始攻击
                if (distance <= m_SquashData.AttackRange)
                {
                    Logger.Log("SquashAttackStrategy", $"{Owner.name} 僵尸 {targetZombie.name} 已进入攻击范围，距离: {distance:F2}");
                    yield break;
                }
                
                // 如果僵尸在跳跃范围内，也可以开始攻击（因为可以跳跃过去）
                if (distance <= m_SquashData.JumpRange)
                {
                    Logger.Log("SquashAttackStrategy", $"{Owner.name} 僵尸 {targetZombie.name} 在跳跃范围内，距离: {distance:F2}，可以开始攻击");
                    yield break;
                }
                
                nextCheckTime = elapsedTime + checkInterval;
            }
            
            yield return null;
        }

        // 如果超时或目标无效，检查是否仍然可以攻击
        if (targetZombie != null && !targetZombie.HealthComponent.IsDead && Owner != null)
        {
            float finalDistance = Vector3.Distance(Owner.transform.position, targetZombie.transform.position);
            if (finalDistance > m_SquashData.JumpRange)
            {
                Logger.LogWarning("SquashAttackStrategy", $"{Owner.name} 等待超时，僵尸 {targetZombie.name} 距离: {finalDistance:F2}，超出跳跃范围 {m_SquashData.JumpRange}");
            }
        }
    }

    /// <summary>
    /// 等待攻击动画播放完成
    /// </summary>
    private IEnumerator WaitForAttackAnimation()
    {
        if (Owner == null || Owner.Animator == null)
        {
            Logger.LogWarning("SquashAttackStrategy", "Owner或Animator为空，无法等待攻击动画");
            yield break;
        }

        // 等待几帧，确保动画状态已经切换并开始播放
        yield return null;
        yield return null;
        yield return null;

        // 等待动画真正开始播放（检查normalizedTime是否大于0）
        float waitForStartTime = 0f;
        float maxWaitForStart = 0.5f; // 最多等待0.5秒让动画开始
        bool animationStarted = false;
        
        while (waitForStartTime < maxWaitForStart && Owner != null && Owner.Animator != null)
        {
            AnimatorStateInfo stateInfo = Owner.Animator.GetCurrentAnimatorStateInfo(0);
            
            // 检查是否在攻击状态，并且动画已经开始播放
            if (Owner.FSMComponent != null && Owner.FSMComponent.State == FSMType.Attack)
            {
                // 检查动画是否在播放（normalizedTime > 0 或动画长度 > 0）
                if (stateInfo.length > 0 && (stateInfo.normalizedTime > 0 || stateInfo.IsName("Attack")))
                {
                    animationStarted = true;
                    Logger.Log("SquashAttackStrategy", $"{Owner.name} 攻击动画已开始播放，normalizedTime: {stateInfo.normalizedTime:F2}");
                    break;
                }
            }
            
            waitForStartTime += Time.deltaTime;
            yield return null;
        }

        if (!animationStarted)
        {
            Logger.LogWarning("SquashAttackStrategy", $"{Owner.name} 攻击动画可能未正确开始播放");
            yield break;
        }

        // 获取当前播放的动画信息
        AnimatorStateInfo currentStateInfo = Owner.Animator.GetCurrentAnimatorStateInfo(0);
        
        // 获取动画长度
        float animationLength = currentStateInfo.length;
        
        // 如果动画长度无效，使用默认值
        if (animationLength <= 0)
        {
            animationLength = 1f; // 默认1秒
            Logger.LogWarning("SquashAttackStrategy", $"{Owner.name} 无法获取攻击动画长度，使用默认值1秒");
        }

        // 保存状态hash用于比较
        int stateHash = currentStateInfo.fullPathHash;
        float startNormalizedTime = currentStateInfo.normalizedTime;
        
        Logger.Log("SquashAttackStrategy", $"{Owner.name} 开始等待攻击动画播放完成，动画长度: {animationLength}秒，当前normalizedTime: {startNormalizedTime:F2}");

        // 等待动画播放完成
        float maxWaitTime = animationLength * 2f; // 最大等待时间（动画长度的2倍，防止无限等待）
        float elapsedTime = 0f;
        
        while (elapsedTime < maxWaitTime && Owner != null && Owner.Animator != null)
        {
            // 检查是否仍在攻击状态
            if (Owner.FSMComponent == null || Owner.FSMComponent.State != FSMType.Attack)
            {
                Logger.Log("SquashAttackStrategy", $"{Owner.name} 已离开攻击状态，停止等待动画");
                break;
            }
            
            // 获取当前动画状态
            AnimatorStateInfo currentState = Owner.Animator.GetCurrentAnimatorStateInfo(0);
            
            // 检查是否仍在同一个动画状态
            if (currentState.fullPathHash != stateHash)
            {
                // 动画状态已切换，可能动画已经结束或被打断
                Logger.Log("SquashAttackStrategy", $"{Owner.name} 攻击动画状态已切换，动画可能已结束");
                break;
            }
            
            // 检查动画是否已经播放完成
            // 确保normalizedTime确实从开始值增长到了1（防止一开始就是1的情况）
            if (currentState.normalizedTime >= 1f && currentState.normalizedTime > startNormalizedTime)
            {
                Logger.Log("SquashAttackStrategy", $"{Owner.name} 攻击动画播放完成，normalizedTime: {currentState.normalizedTime:F2}");
                break;
            }
            
            elapsedTime += Time.deltaTime;
            yield return null;
        }

        Logger.Log("SquashAttackStrategy", $"{Owner.name} 攻击动画等待完成，总等待时间: {elapsedTime:F2}秒");
    }

    /// <summary>
    /// 跳跃到目标位置
    /// </summary>
    private IEnumerator JumpToTarget(Vector3 targetPosition)
    {
        if (Owner == null) yield break;

        Vector3 startPosition = Owner.transform.position;
        // 保持Y坐标不变（窝瓜在地面上移动）
        targetPosition.y = startPosition.y;
        float jumpHeight = 1.0f; // 跳跃高度
        float jumpDuration = 0.3f; // 跳跃持续时间
        float elapsed = 0f;

        Logger.Log("SquashAttackStrategy", $"{Owner.name} 开始跳跃到 {targetPosition}");

        while (elapsed < jumpDuration && Owner != null)
        {
            elapsed += Time.deltaTime;
            float t = elapsed / jumpDuration;
            
            // 使用抛物线轨迹
            Vector3 currentPos = Vector3.Lerp(startPosition, targetPosition, t);
            currentPos.y += Mathf.Sin(t * Mathf.PI) * jumpHeight;
            
            Owner.transform.position = currentPos;
            yield return null;
        }

        // 确保最终位置准确（Y坐标保持原样）
        if (Owner != null)
        {
            Vector3 finalPosition = targetPosition;
            finalPosition.y = Owner.transform.position.y; // 保持当前Y坐标
            Owner.transform.position = finalPosition;
            Logger.Log("SquashAttackStrategy", $"{Owner.name} 跳跃完成");
        }
    }

    public override void Cancel()
    {
        if (m_AttackCoroutine != null && Owner != null)
        {
            Owner.StopCoroutine(m_AttackCoroutine);
            m_AttackCoroutine = null;
        }
    }
}

